﻿/**************************************************************
 *
 * 唯一标识：9a2dbbf8-e05f-437d-8de3-47960bfdfb91
 * 命名空间：Sgr.Threading
 * 创建时间：2024/6/20 16:45:00
 * 机器名称：DESKTOP-HJ4OAG9
 * 创建者：CocoYuan
 * 电子邮箱：fengqinhua2016@163.com
 * 描述：提供无锁的原子 bool 读写与条件更新操作。
 *
 **************************************************************/

using System.Runtime.CompilerServices;

namespace Sgr.Threading
{
    /// <summary>
    /// 提供针对 <see cref="bool"/> 的无锁原子读写与条件更新操作。
    /// 内部以 <c>int</c> 表示：0 = false，1 = true。
    /// </summary>
    public sealed class AtomicBoolean
    {
        private int _value; // 0 = false, 1 = true

        /// <summary>
        /// 初始化为 false。
        /// </summary>
        public AtomicBoolean() : this(false) { }

        /// <summary>
        /// 使用指定初始值初始化。
        /// </summary>
        public AtomicBoolean(bool value)
        {
            _value = ToInt(value);
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private static int ToInt(bool value) => value ? 1 : 0;

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private static bool ToBool(int value) => value != 0;

        /// <summary>
        /// 原子读取当前值（具备内存可见性）。
        /// </summary>
        public bool Get()
        {
            return ToBool(Volatile.Read(ref _value));
        }

        /// <summary>
        /// 原子设置为新值（具备写入内存栅栏）。
        /// </summary>
        public void Set(bool value)
        {
            Interlocked.Exchange(ref _value, ToInt(value));
        }

        /// <summary>
        /// 原子读取旧值并设置为新值，返回旧值。
        /// </summary>
        public bool GetAndSet(bool value)
        {
            return ToBool(Interlocked.Exchange(ref _value, ToInt(value)));
        }

        /// <summary>
        /// 若当前值等于 expected，则原子更新为 result。
        /// 成功返回 true，失败返回 false。
        /// </summary>
        public bool CompareAndSet(bool expected, bool result)
        {
            int e = ToInt(expected);
            int r = ToInt(result);
            return Interlocked.CompareExchange(ref _value, r, e) == e;
        }

        /// <summary>
        /// 原子尝试从旧值 oldValue 更新为 newValue；等价于 <see cref="CompareAndSet"/>.
        /// </summary>
        public bool TrySet(bool oldValue, bool newValue) => CompareAndSet(oldValue, newValue);

        /// <summary>
        /// 若当前为 false，则设置为 true，并返回是否成功将其置为 true。
        /// </summary>
        public bool TrySetTrue()
        {
            return Interlocked.CompareExchange(ref _value, 1, 0) == 0;
        }

        /// <summary>
        /// 若当前为 true，则设置为 false，并返回是否成功将其置为 false。
        /// </summary>
        public bool TrySetFalse()
        {
            return Interlocked.CompareExchange(ref _value, 0, 1) == 1;
        }

        /// <summary>
        /// 隐式转换为 bool。
        /// </summary>
        public static implicit operator bool(AtomicBoolean value) => value.Get();

        /// <summary>
        /// 便于调试输出。
        /// </summary>
        public override string ToString() => Get().ToString();
    }
}